#include "Task.hpp"
#include <iostream>
#include <string>
#include <ctime>
#include <unistd.h>
#include <sys/types.h>
#include <vector>
#include <sys/wait.h>
#include <sys/types.h>
using namespace std;


const int processcnt = 10;
vector<task_t> tasks;

// 先描述
class channel
{
public:
    channel(int cmdfd, int slaveid, string processname)
        : _cmdfd(cmdfd)
        , _slaveid(slaveid)
        , _processname(processname)
    {}

public:
    int _cmdfd;             // 发送任务的文件描述符
    int _slaveid;          // 子进程pid
    string _processname;    // 子进程名字 -- 方便打印日志
};


void slaver()
{
    while(true)
    {
        int cmdcode = 0;
        ssize_t n = read(0, &cmdcode, sizeof(int));
        if(n == sizeof(int))
        {
            cout << "slaveid: " << getpid() << " get a command: " << " cmdcode: " << cmdcode << endl;
            if(cmdcode >= 0 && cmdcode < tasks.size())
                tasks[cmdcode]();
        }
        if(n == 0)
            break;
    }
}


void InitProcessPool(vector<channel>* channels)
{
    vector<int> oldfd;

    for(int i = 0; i < processcnt; i++)
    {
        int pipefd[2] = {0};    // 临时空间
        pipe(pipefd);

        pid_t id = fork();
        if(id == 0)
        {
            // child
            cout << "close histroy fd: ";
            for(auto& fd : oldfd)
            {
                cout << fd << " ";
                close(fd);
            }
            cout << endl;

            close(pipefd[1]);   // 关闭子进程写端
            dup2(pipefd[0], 0); // 重定向读端
            close(pipefd[0]);
            slaver();

            cout << "process " << getpid() << " quit" << endl;
            exit(0);
        }
        else if(id > 0)
        {
            // father
            close(pipefd[0]);    // 关闭父进程读端

            string name = "process-" + to_string(i);
            channels->push_back(channel(pipefd[1], id, name));

            oldfd.push_back(pipefd[1]);

            sleep(1);
        }
        else
            break;
    }
}


void CtrlSlave(const vector<channel>& channels)
{
    int which = 0; // 轮询
    // while(true)
    for(int i = 1; i <= 100; i++)
    {
        // 1、选择任务
        int cmdcode = rand() % tasks.size();

        // 2、选择进程
        // int processpos = rand() % cahnnels.size(); // 随机访问

        // 3、发送任务
        cout << "father say cmdcode : " << cmdcode << " already sendto " << channels[which]._slaveid 
            << " process name: " << channels[which]._processname << endl;
        write(channels[which]._cmdfd, &cmdcode, sizeof(cmdcode));

        which++;
        which %= channels.size();

        sleep(1);
    }
}


void QuitProcessPool(const vector<channel>& channels)
{
    for(auto& proc : channels)
    {
        close(proc._cmdfd);
        waitpid(proc._slaveid, nullptr, 0);
    }

    // for(auto& proc : channels)
    //     close(proc._cmdfd);
    // sleep(5);
    // for(auto proc : channels)
    //     waitpid(proc._slaveid, nullptr, 0);
    // sleep(5);
}


int main()
{
    // 加载任务列表
    LoadTask(&tasks);

    srand((unsigned int)time(nullptr)^getpid()^954);
    // 1、初始化
    vector<channel> channels;
    InitProcessPool(&channels);

    // 2、控制子进程
    CtrlSlave(channels);

    // 3、清理资源
    QuitProcessPool(channels);

    return 0;
}